From 159de248eae208b392567a5d6cca362d7170285d Mon Sep 17 00:00:00 2001 From: oliskoli Date: Sun, 7 May 2006 17:46:57 +0000 Subject: [PATCH] Add new module 'axim_gpb', a track reader for Dell Axim Navigation System (.gpb) files. --- axim_gpb.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 axim_gpb.c diff --git a/axim_gpb.c b/axim_gpb.c new file mode 100644 index 000000000..9a16fcfc5 --- /dev/null +++ b/axim_gpb.c @@ -0,0 +1,184 @@ +/* + + Track reader for "Dell Axim Navigation System" GPB files, + + Copyright (C) 2006 Olaf Klein, o.b.klein@t-online.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include +#include +#include + +#define MYNAME "axim_gpb" + +#define RECORD_LEN 344 + +static FILE *fin, *fout; +static char dbginfo = 1; + +static +arglist_t axim_gpb_args[] = { + ARG_TERMINATOR +}; + +static float +le_read32_float(const void *src) +{ + float f; + gbint32 i; + + i = le_read32(src); + memcpy(&f, &i, 4); + + return f; +} + +static void +decode_buff(const char *buff, route_head *track) +{ + struct tm tm; + double lat, lon, alt, dir; + float vdop, hdop, pdop, spd, Uf1; + int sats; + waypoint *wpt; + + wpt = waypt_new(); + + memset(&tm, '\0', sizeof(tm)); + + tm.tm_year = le_read16((void *) (buff + 16)); + tm.tm_mon = le_read16((void *) (buff + 18)); + tm.tm_mday = le_read16((void *) (buff + 22)); + tm.tm_hour = le_read16((void *) (buff + 24)); + tm.tm_min = le_read16((void *) (buff + 26)); + tm.tm_sec = le_read16((void *) (buff + 28)); + + le_read64(&lat, (void *) (buff + 32)); + le_read64(&lon, (void *) (buff + 40)); + spd = le_read32_float((void *) (buff + 48)); + dir = le_read32_float((void *) (buff + 52)); + + alt = le_read32_float((void *) (buff + 64)); + Uf1 = le_read32_float((void *) (buff + 68)); + + hdop = le_read32_float((void *) (buff + 84)); + vdop = le_read32_float((void *) (buff + 88)); + pdop = le_read32_float((void *) (buff + 92)); + sats = le_read16((void *) (buff + 96)); + + wpt->latitude = lat; + wpt->longitude = lon; + wpt->altitude = alt; +#if 0 + /* These values can be, but must not be right. */ + /* Further checks are needed to verify that. */ + /* (!!! reference data !!!) */ + wpt->course = dir; + wpt->hdop = hdop; + wpt->vdop = vdop; + wpt->pdop = pdop; + wpt->sat = sats; + wpt->speed = spd * 10; +#endif + /* We don't have a header with some magic fixed numbers or strings. */ + /* So let us check the range for some basic values */ + + is_fatal( + (tm.tm_year < 2005) || + (tm.tm_mon < 1) || (tm.tm_mon > 12) || + (tm.tm_mday < 1) || (tm.tm_mday > 31) || + (tm.tm_hour > 23) || (tm.tm_min > 60) || (tm.tm_sec > 60), + MYNAME ": Invalid or unsupported file (invalid time-stamp)."); + is_fatal( + (fabs(wpt->latitude) > 180) || + (fabs(wpt->longitude) > 90), + MYNAME ": Invalid or unsupported file (lat or/and lon out of range)."); + + /* post work */ + + tm.tm_year-=1900; + tm.tm_mon--; + wpt->creation_time = mkgmtime(&tm); + + track_add_wpt(track, wpt); +} + +/******************************************************************************* +* %%% global callbacks called by gpsbabel main process %%% * +*******************************************************************************/ + +static void +axim_gpb_rd_init(const char *fname) +{ + fin = xfopen(fname, "rb", MYNAME); +} + +static void +axim_gpb_rd_deinit(void) +{ + fclose(fin); +} + +static void +axim_gpb_read(void) +{ + char buff[RECORD_LEN]; + route_head *track = NULL; + size_t bytes; + off_t filesize, left; + + fseek(fin, 0, SEEK_END); + filesize = ftell(fin); + + left = filesize - ((filesize / RECORD_LEN) * RECORD_LEN); + is_fatal((left != 0), MYNAME ": Invalid or unsupported file (filesize)."); + + fseek(fin, 0, SEEK_SET); /* seek file to start */ + + while ((bytes = fread(buff, 1, RECORD_LEN, fin))) + { + if (track == NULL) + { + track = route_head_alloc(); + track_add_head(track); + } + decode_buff(buff, track); + } +} + +/**************************************************************************/ + +ff_vecs_t axim_gpb_vecs = { + ff_type_file, + { + ff_cap_none /* waypoints */, + ff_cap_read /* tracks */, + ff_cap_none /* routes */, + }, + axim_gpb_rd_init, + NULL, + axim_gpb_rd_deinit, + NULL, + axim_gpb_read, + NULL, + NULL, + axim_gpb_args, + CET_CHARSET_ASCII, 0 +}; +/**************************************************************************/ -- 2.30.2